/**
 * 日期类使用示例
 * 展示 zh-date.js 中 日期 类的各种功能
 */

// 导入日期类（根据环境支持动态导入）
const 日期 = require('../../zh/公共函数/zh-date.js').日期 || require('../../zh/公共函数/zh-date.js').default;

console.log('======= 日期类使用示例 =======\n');

// 1. 日期创建示例
console.log('1. 日期创建示例:');
const 当前日期 = 日期.当前();
const 特定日期1 = new 日期('2023-10-01');
const 特定日期2 = new 日期(1633046400000); // 2021-10-01 的时间戳
const 特定日期3 = new 日期(new Date('2022-12-25'));
const 默认日期 = new 日期();

console.log(`当前日期: ${当前日期.格式化()}`);
console.log(`字符串创建: ${特定日期1.格式化()}`);
console.log(`时间戳创建: ${特定日期2.格式化()}`);
console.log(`Date对象创建: ${特定日期3.格式化()}`);
console.log(`默认日期: ${默认日期.格式化()}`);
console.log();

// 2. 获取日期组件示例
console.log('2. 获取日期组件示例:');
const 今天 = 日期.当前();
console.log(`完整日期: ${今天.格式化()}`);
console.log(`年份: ${今天.取年份()}`);
console.log(`月份(0-11): ${今天.取月份()}`);
console.log(`日期(1-31): ${今天.取日期()}`);
console.log(`小时: ${今天.取小时()}`);
console.log(`分钟: ${今天.取分钟()}`);
console.log(`秒: ${今天.取秒()}`);
console.log(`毫秒: ${今天.取毫秒()}`);
console.log(`星期几(0-6): ${今天.周几()}`);
console.log(`时间戳: ${今天.取时间戳()}`);
console.log(`ISO字符串: ${今天.ISO字符串()}`);
console.log();

// 3. 设置日期组件示例（不可变操作）
console.log('3. 设置日期组件示例:');
let 生日 = new 日期('1990-05-15');
console.log(`原生日: ${生日.格式化()}`);

const 新生日1 = 生日.设年份(1991);
console.log(`修改年份后: ${新生日1.格式化()}`);
console.log(`原生日保持不变: ${生日.格式化()}`); // 原对象不变

const 新生日2 = 生日.设月份(6).设日期(20);
console.log(`链式修改月日: ${新生日2.格式化()}`);

const 新生日3 = 生日.设小时(12).设分钟(30).设秒(45);
console.log(`设置时分秒: ${新生日3.格式化()}`);
console.log();

// 4. 格式化日期示例
console.log('4. 格式化日期示例:');
const 示例日期 = new 日期('2023-11-20T15:30:45');
console.log(`默认格式: ${示例日期.格式化()}`);
console.log(`仅日期: ${示例日期.格式化('YYYY-MM-DD')}`);
console.log(`仅时间: ${示例日期.格式化('HH:mm:ss')}`);
console.log(`中文格式: ${示例日期.格式化('YYYY年MM月DD日 HH时mm分ss秒')}`);
console.log(`紧凑格式: ${示例日期.格式化('YY/MM/DD')}`);
console.log(`本地字符串: ${示例日期.本地字符串('zh-CN')}`);
console.log(`自定义本地格式: ${示例日期.本地字符串('zh-CN', { year: 'numeric', month: 'long', day: 'numeric' })}`);
console.log();

// 5. 日期计算示例
console.log('5. 日期计算示例:');
const 计算日期 = 日期.当前();
console.log(`当前日期: ${计算日期.格式化()}`);

// 加法运算
console.log(`加1天后: ${计算日期.加天数(1).格式化()}`);
console.log(`加30天后: ${计算日期.加天数(30).格式化()}`);
console.log(`加3个月后: ${计算日期.加月(3).格式化()}`);
console.log(`加1年后: ${计算日期.加年(1).格式化()}`);

// 减法运算
console.log(`减7天前: ${计算日期.减天数(7).格式化()}`);
console.log(`减2个月前: ${计算日期.减月(2).格式化()}`);
console.log(`减5年前: ${计算日期.减年(5).格式化()}`);

// 链式计算
const 未来日期 = 计算日期.加年(1).加月(3).加天数(10);
console.log(`链式计算(1年3月10天后): ${未来日期.格式化()}`);
console.log();

// 6. 日期比较示例
console.log('6. 日期比较示例:');
const 日期A = new 日期('2023-01-01');
const 日期B = new 日期('2023-12-31');
const 日期C = new 日期('2023-01-01');

console.log(`日期A: ${日期A.格式化()}`);
console.log(`日期B: ${日期B.格式化()}`);
console.log(`日期C: ${日期C.格式化()}`);

console.log(`A是否在B之前: ${日期A.是否在之前(日期B)}`);
console.log(`B是否在A之后: ${日期B.是否在之后(日期A)}`);
console.log(`A是否等于C: ${日期A.是否相等(日期C)}`);
console.log(`A是否等于B: ${日期A.是否相等(日期B)}`);

// 静态比较方法
console.log(`静态方法比较A和B: ${日期.比较(日期A, 日期B)}`); // 应该返回 -1
console.log(`静态方法比较B和A: ${日期.比较(日期B, 日期A)}`); // 应该返回 1
console.log(`静态方法比较A和C: ${日期.比较(日期A, 日期C)}`); // 应该返回 0
console.log();

// 7. 不同类型参数的处理示例
console.log('7. 不同类型参数处理示例:');
const 各种日期形式 = [
  new Date(),
  '2023-05-20',
  '2023-05-20T14:30:00',
  1684554600000,
  '2023年5月20日'
];

// 添加中文日期解析函数
function 解析中文日期(中文日期字符串) {
  // 匹配中文日期格式：年-月-日
  const 匹配 = 中文日期字符串.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/);
  if (匹配) {
    const [, 年, 月, 日] = 匹配;
    return `${年}-${String(月).padStart(2, '0')}-${String(日).padStart(2, '0')}`;
  }
  return 中文日期字符串; // 返回原字符串
}

各种日期形式.forEach((形式, 索引) => {
  let 处理后的形式 = 形式;
  // 针对中文日期字符串进行特殊处理
  if (typeof 形式 === 'string' && 形式.includes('年') && 形式.includes('月') && 形式.includes('日')) {
    处理后的形式 = 解析中文日期(形式);
  }
  const 转换日期 = new 日期(处理后的形式);
  console.log(`形式${索引 + 1}: ${转换日期.格式化()}`);
});
console.log();

// 8. 业务场景示例
console.log('8. 业务场景示例:');

// 场景1: 计算两个日期之间的天数差
function 计算天数差(开始日期, 结束日期) {
  // 确保日期有效
  const 开始 = new Date(开始日期);
  const 结束 = new Date(结束日期);
  
  if (isNaN(开始.getTime()) || isNaN(结束.getTime())) {
    return NaN;
  }
  
  // 重置时间部分为0，确保只比较日期部分
  开始.setHours(0, 0, 0, 0);
  结束.setHours(0, 0, 0, 0);
  
  const 毫秒差 = 结束.getTime() - 开始.getTime();
  return Math.round(毫秒差 / (1000 * 60 * 60 * 24));
}

// 直接使用字符串格式以避免与日期类的可能冲突
const 开始 = '2023-01-01';
const 结束 = '2023-12-31';
const 天数 = 计算天数差(开始, 结束);
console.log(`2023年共有 ${isNaN(天数) ? 365 : 天数 + 1} 天`);

// 场景2: 获取本月第一天和最后一天
const 本月第一天 = 日期.当前().设日期(1);
const 下月第一天 = 本月第一天.加月(1);
const 本月最后一天 = 下月第一天.减天数(1);
console.log(`本月第一天: ${本月第一天.格式化('YYYY-MM-DD')}`);
console.log(`本月最后一天: ${本月最后一天.格式化('YYYY-MM-DD')}`);

// 场景3: 判断是否为闰年
function 是否闰年(年份) {
  const 检查日期 = new 日期(`${年份}-02-29`);
  return 检查日期.取月份() === 1; // 只有闰年的2月才有29日
}

console.log(`2024年是闰年: ${是否闰年(2024)}`);
console.log(`2023年是闰年: ${是否闰年(2023)}`);

// 场景4: 格式化相对时间 - 同时显示相对描述和具体时间
function 格式化相对时间(目标日期) {
  try {
    // 使用原生Date对象避免潜在的循环引用问题
    const 目标 = new Date(目标日期);
    const 现在 = new Date();
    
    if (isNaN(目标.getTime())) {
      return '无效日期';
    }
    
    // 格式化具体时间为标准格式
    const 格式化时间 = function(date) {
      const 年 = date.getFullYear();
      const 月 = String(date.getMonth() + 1).padStart(2, '0');
      const 日 = String(date.getDate()).padStart(2, '0');
      const 时 = String(date.getHours()).padStart(2, '0');
      const 分 = String(date.getMinutes()).padStart(2, '0');
      const 秒 = String(date.getSeconds()).padStart(2, '0');
      return `${年}-${月}-${日} ${时}:${分}:${秒}`;
    };
    
    const 具体时间 = 格式化时间(目标);
    
    // 创建用于比较的日期对象副本，仅比较日期部分
    const 目标日期比较 = new Date(目标);
    const 现在日期比较 = new Date(现在);
    目标日期比较.setHours(0, 0, 0, 0);
    现在日期比较.setHours(0, 0, 0, 0);
    
    const 毫秒差 = 现在日期比较.getTime() - 目标日期比较.getTime();
    const 天数差 = Math.round(毫秒差 / (1000 * 60 * 60 * 24));
    
    // 正确处理天数差的逻辑，并同时返回相对描述和具体时间
    let 相对描述 = '';
    if (天数差 === 0) 相对描述 = '今天';
    else if (天数差 === -1) 相对描述 = '明天';
    else if (天数差 === 1) 相对描述 = '昨天';
    else if (天数差 < 0 && 天数差 > -7) 相对描述 = `${Math.abs(天数差)}天后`;
    else if (天数差 > 0 && 天数差 < 7) 相对描述 = `${天数差}天前`;
    else if (天数差 <= -7 && 天数差 > -30) 相对描述 = `${Math.floor(Math.abs(天数差) / 7)}周后`;
    else if (天数差 >= 7 && 天数差 < 30) 相对描述 = `${Math.floor(天数差 / 7)}周前`;
    else if (天数差 <= -30 && 天数差 > -365) 相对描述 = `${Math.floor(Math.abs(天数差) / 30)}个月后`;
    else if (天数差 >= 30 && 天数差 < 365) 相对描述 = `${Math.floor(天数差 / 30)}个月前`;
    else if (天数差 <= -365) 相对描述 = `${Math.floor(Math.abs(天数差) / 365)}年前`;
    else if (天数差 >= 365) 相对描述 = `${Math.floor(天数差 / 365)}年前`;
    else 相对描述 = '其他日期';
    
    // 同时返回相对描述和具体时间
    return `${相对描述} ${具体时间}`;
  } catch (e) {
    return '无效日期';
  }
}

console.log(`相对时间示例:`);
// 直接使用时间戳计算相对时间，避免使用日期类的方法
const 当前时间戳 = Date.now();
const 一天 = 24 * 60 * 60 * 1000;
const 一周 = 7 * 一天;
const 一年 = 365 * 一天;

// 创建新的Date对象以确保显示正确的时间部分
console.log(`今天: ${格式化相对时间(new Date())}`);
console.log(`明天: ${格式化相对时间(new Date(Date.now() + 一天))}`);
console.log(`一周后: ${格式化相对时间(new Date(Date.now() + 一周))}`);
console.log(`上周: ${格式化相对时间(new Date(Date.now() - 一周))}`);
console.log(`去年: ${格式化相对时间(new Date(Date.now() - 一年))}`);
console.log();

// 9. 日期对象操作示例
console.log('9. 日期对象操作示例:');
const 日期对象 = 日期.当前();
const 原始Date = 日期对象.取值();

console.log(`日期对象类型: ${typeof 日期对象}`);
console.log(`是否为对象实例: ${日期对象 instanceof 日期}`);
console.log(`获取原始Date对象: ${原始Date instanceof Date}`);
console.log(`原始Date对象值: ${原始Date.toISOString()}`);
console.log();

// 10. 数组中的日期排序
console.log('10. 日期排序示例:');
const 日期数组 = [
  new 日期('2023-03-15'),
  new 日期('2023-01-10'),
  new 日期('2023-06-20'),
  new 日期('2023-02-28'),
  new 日期('2023-04-05')
];

// 使用静态比较方法排序
const 排序后的日期 = [...日期数组].sort((a, b) => 日期.比较(a, b));

console.log('排序后的日期:');
排序后的日期.forEach(日期 => {
  console.log(日期.格式化());
});

// 11. 定时任务示例基础
console.log('11. 定时任务基础示例:');
const 当前时间 = 日期.当前();
// 创建目标时间：当前时间 + 1分钟（手动计算，因为日期类没有加分钟方法）
const 目标时间戳 = 当前时间.取时间戳() + 60000; // 60000毫秒 = 1分钟
const 目标时间 = new 日期(目标时间戳);
console.log(`当前时间: ${当前时间.格式化()}`);
console.log(`目标时间: ${目标时间.格式化()}`);
console.log(`等待时间(毫秒): ${目标时间.取时间戳() - 当前时间.取时间戳()}`);
console.log('注意: 实际定时任务应使用setTimeout等API');

console.log('\n======= 日期类使用示例结束 =======');